﻿using Nop.Core;
using Nop.Core.Domain.Orders;
using Nop.Core.Domain.Payments;
using Nop.Plugin.Payments.LibraPay.Models;
using Nop.Services.Configuration;
using Nop.Services.Localization;
using Nop.Services.Logging;
using Nop.Services.Orders;
using Nop.Services.Payments;
using Nop.Web.Framework;
using Nop.Web.Framework.Controllers;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Web.Mvc;

namespace Nop.Plugin.Payments.LibraPay.Controllers
{
	/// <summary>
	///		<para>Takes the customer from order, to payment gateway, to confirmation page.</para>
	/// </summary>
	public class PaymentLibraPayController : BasePaymentController
	{
		private readonly ISettingService _settingService;
		private readonly IPaymentService _paymentService;
		private readonly IOrderService _orderService;
		private readonly IOrderProcessingService _orderProcessingService;
		private readonly ILogger _logger;
		private readonly IWebHelper _webHelper;
		private readonly ILocalizationService _localizationService;
		private readonly LibraPayPaymentSettings _LibraPayPaymentSettings;
		private readonly PaymentSettings _paymentSettings;

		public PaymentLibraPayController(ISettingService settingService,
			IPaymentService paymentService, IOrderService orderService,
			IOrderProcessingService orderProcessingService,
			ILogger logger, IWebHelper webHelper,
			ILocalizationService localizationService,
			LibraPayPaymentSettings LibraPayPaymentSettings,
			PaymentSettings paymentSettings)
		{
			this._settingService = settingService;
			this._paymentService = paymentService;
			this._orderService = orderService;
			this._orderProcessingService = orderProcessingService;
			this._logger = logger;
			this._webHelper = webHelper;
			this._localizationService = localizationService;
			this._LibraPayPaymentSettings = LibraPayPaymentSettings;
			this._paymentSettings = paymentSettings;
		}

		/// <summary>
		///		<para>Displays a form to ask for merchant-specific config settings...</para>
		///		<para>the ones used by the LibraPay plugin to work with payment gateway API.</para>
		/// </summary>
		/// <returns></returns>
		[AdminAuthorize]
		[ChildActionOnly]
		public ActionResult Configure()
		{
			ConfigurationModel model = new ConfigurationModel();
			model.UseSandbox = _LibraPayPaymentSettings.UseSandbox;
			model.NotifyBeforeRedirect = _LibraPayPaymentSettings.NotifyBeforeRedirect;
			model.MerchantName = _LibraPayPaymentSettings.MerchantName;
			model.MerchantURL = _LibraPayPaymentSettings.MerchantURL;
			model.MerchantEmail = _LibraPayPaymentSettings.MerchantEmail;
			model.EncryptionKey = _LibraPayPaymentSettings.EncryptionKey;
			model.TerminalId = _LibraPayPaymentSettings.TerminalId;
			model.AdditionalFee = _LibraPayPaymentSettings.AdditionalFee;
			model.URLforIPN = _webHelper.GetStoreLocation() + "Plugins/PaymentLibraPay/Authorize_IPN";

			ViewBag.InstantPaymentNotificationURL = _webHelper.GetStoreLocation() + "Plugins/PaymentLibraPay/Authorize_IPN";
			return View("~/Plugins/Payments.LibraPay/Views/PaymentLibraPay/Configure.cshtml", model);
		}

		/// <summary>
		///		<para>Takes merchant-specific config settings.</para>
		///		<para>Saves those configuration settings for the LibraPay plugin to work with payment gateway API.</para>
		/// </summary>
		/// <returns></returns>
		[HttpPost]
		[AdminAuthorize]
		[ChildActionOnly]
		public ActionResult Configure(ConfigurationModel model)
		{
			if (!ModelState.IsValid)
				return Configure();

			//save settings
			_LibraPayPaymentSettings.UseSandbox = model.UseSandbox;
			_LibraPayPaymentSettings.NotifyBeforeRedirect = model.NotifyBeforeRedirect;
			_LibraPayPaymentSettings.MerchantName = model.MerchantName;
			_LibraPayPaymentSettings.MerchantURL = model.MerchantURL;
			_LibraPayPaymentSettings.MerchantEmail = model.MerchantEmail;
			_LibraPayPaymentSettings.EncryptionKey = model.EncryptionKey;
			_LibraPayPaymentSettings.TerminalId = model.TerminalId;
			_LibraPayPaymentSettings.AdditionalFee = model.AdditionalFee;

			if (!(_LibraPayPaymentSettings.MerchantURL.ToLower().StartsWith("http://") || _LibraPayPaymentSettings.MerchantURL.ToLower().StartsWith("https://")))
			{
				_LibraPayPaymentSettings.MerchantURL = "http://" + _LibraPayPaymentSettings.MerchantURL;
			}
			_settingService.SaveSetting(_LibraPayPaymentSettings);

			this._logger.Information("LibraPay plugin configuration: using PaymentGatewayURL_Test > " + LibraPayPaymentSettings.PaymentGatewayURL_Test);
			this._logger.Information("LibraPay plugin configuration: using PaymentGatewayURL_Live > " + LibraPayPaymentSettings.PaymentGatewayURL_Live);
			this._logger.Information("LibraPay plugin configuration has been saved.");

			model.URLforIPN = _webHelper.GetStoreLocation() + "Plugins/PaymentLibraPay/Authorize_IPN";
			ViewBag.Confirmation = this._localizationService.GetResource("Plugins.Payments.LibraPay.Config.SettingsWereSaved");
			return View("~/Plugins/Payments.LibraPay/Views/PaymentLibraPay/Configure.cshtml", model);
		}

		/// <summary>
		///		<para>Simply display a notification to customer that he/she will be redirected to LibraPay gateway for actual payment.</para>
		///		<para>Also may show basic order info: description, order id reference, amount and currency.</para>
		/// </summary>
		/// <returns></returns>
		[ChildActionOnly]
		public ActionResult PaymentInfo()
		{
			return View("~/Plugins/Payments.LibraPay/Views/PaymentLibraPay/PaymentInfo.cshtml");
		}

		/// <summary>
		///		<para>Prepares a FORM (inside a View) to be POST-ed to LibraPay payment gateway API. The view also notifies the user about being redirected.</para>
		///		<para>The customer will "authorize" the payment: it means blocking money on the credit card when the visitor places an order.</para>
		/// </summary>
		/// <param name="OrderID">The order being paid upon placing.</param>
		/// <returns></returns>
		public ActionResult AuthorizeRequest(int OrderID)
		{
			Order yeOrder = this._orderService.GetOrderById(OrderID);
			#region check if order exists and has proper state
			if (yeOrder == null || yeOrder.Deleted)
			{
				ViewBag.ErrorTitle = this._localizationService.GetResource("Plugins.Payments.LibraPay.Error.InvalidOrder");
				ViewBag.ErrorMessage = string.Format(this._localizationService.GetResource("Plugins.Payments.LibraPay.Error.NonExistent"), OrderID);
				return View("~/Plugins/Payments.LibraPay/Views/PaymentLibraPay/Authorize.cshtml");
			}
			if (yeOrder.PaymentStatus != PaymentStatus.Pending)
			{
				ViewBag.ErrorTitle = this._localizationService.GetResource("Plugins.Payments.LibraPay.Error.InvalidOrder");
				ViewBag.ErrorMessage = string.Format(this._localizationService.GetResource("Plugins.Payments.LibraPay.Error.NotPending"), OrderID);
				return View("~/Plugins/Payments.LibraPay/Views/PaymentLibraPay/Authorize.cshtml");
			}
			#endregion
			string ShippingTaxItemName = this._localizationService.GetResource("Plugins.Payments.LibraPay.Shopper.ShippingTaxItemName");
			string OrderDiscountItemName = this._localizationService.GetResource("Plugins.Payments.LibraPay.Shopper.OrderDiscountItemName");
			AuthorizeModel preAuthFields = new AuthorizeModel();
			preAuthFields.AMOUNT = yeOrder.OrderTotal.ToString("#0.00", CultureInfo.GetCultureInfo("en-us"));
			preAuthFields.CURRENCY = yeOrder.CustomerCurrencyCode.ToUpper();
			preAuthFields.ORDER = (yeOrder.Id + 1000000000).ToString();
			preAuthFields.DESC = this._localizationService.GetResource("Plugins.Payments.LibraPay.Shopper.OrderDescriptionFormat").Replace("{OrderID}", yeOrder.Id.ToString()).Replace("{MerchantName}", _LibraPayPaymentSettings.MerchantName.ToUpper());
			preAuthFields.DESC = LibraPayGatewayMessage.ChopString(preAuthFields.DESC, 50);
			preAuthFields.MERCH_NAME = LibraPayGatewayMessage.ChopString(_LibraPayPaymentSettings.MerchantName, 50);
			preAuthFields.MERCH_URL = LibraPayGatewayMessage.ChopString(_LibraPayPaymentSettings.MerchantURL, 50);
			preAuthFields.MERCHANT = _LibraPayPaymentSettings.TerminalId.PadLeft(15, '0');
			preAuthFields.TERMINAL = _LibraPayPaymentSettings.TerminalId;
			preAuthFields.EMAIL = LibraPayGatewayMessage.ChopString(_LibraPayPaymentSettings.MerchantEmail, 50);
			preAuthFields.TRTYPE = "0";
			preAuthFields.COUNTRY = null;
			preAuthFields.MERCH_GMT = null;
			preAuthFields.TIMESTAMP = DateTime.Now.ToUniversalTime().ToString("yyyyMMddhhmmss");
			preAuthFields.NONCE = Guid.NewGuid().ToString().Replace("-", string.Empty);
			preAuthFields.BACKREF = _webHelper.GetStoreLocation() + "Plugins/PaymentLibraPay/Authorize";
			preAuthFields.DATA_CUSTOM = preAuthFields.ComputeCustomData_AuthorizeRequest(yeOrder, ShippingTaxItemName, OrderDiscountItemName);
			preAuthFields.P_SIGN = preAuthFields.ComputePSign_AuthorizeRequest(_LibraPayPaymentSettings.EncryptionKey);

			preAuthFields.OrderID = yeOrder.Id;
			preAuthFields.Amount = yeOrder.OrderTotal;
			preAuthFields.Description = this._localizationService.GetResource("Plugins.Payments.LibraPay.Shopper.OrderDescriptionFormat").Replace("{OrderID}", yeOrder.Id.ToString()).Replace("{MerchantName}", _LibraPayPaymentSettings.MerchantName.ToUpper());
			#region fill order item details with title, products list and subtotals; this will be displayed to shopper before redirect, if checked in settings
			StringBuilder stbHtmlForOrderItems = new StringBuilder();
			stbHtmlForOrderItems.AppendLine("<table border='0' id='LibraPay_OrderItems'>");
			int productsIndex = 1;
			decimal computedOrderTotal = 0;
			foreach (OrderItem orderItem in yeOrder.OrderItems)
			{
				stbHtmlForOrderItems.AppendLine("<tr>");
				stbHtmlForOrderItems.AppendLine(string.Format("<td align='right'>{0}.</td>", productsIndex));
				stbHtmlForOrderItems.AppendLine(string.Format("<td>{0}</td>", LibraPayGatewayMessage.ChopString(orderItem.Product.Name, 50)));
				stbHtmlForOrderItems.AppendLine(string.Format("<td align='right'>{0:#,##0.00}</td>", orderItem.UnitPriceInclTax));
				stbHtmlForOrderItems.AppendLine("<td>&times;</td>");
				stbHtmlForOrderItems.AppendLine(string.Format("<td align='right'>{0:#,##0}</td>", orderItem.Quantity));
				stbHtmlForOrderItems.AppendLine("<td>=</td>");
				stbHtmlForOrderItems.AppendLine(string.Format("<td align='right'>{0:#,##0.00}</td>", orderItem.PriceInclTax));
				stbHtmlForOrderItems.AppendLine("</tr>");
				computedOrderTotal += orderItem.PriceInclTax;
				productsIndex++;
			}
			if (yeOrder.OrderShippingInclTax != 0M)
			{
				stbHtmlForOrderItems.AppendLine("<tr>");
				stbHtmlForOrderItems.AppendLine(string.Format("<td align='right'>{0}.</td>", productsIndex));
				stbHtmlForOrderItems.AppendLine(string.Format("<td>{0}</td>", ShippingTaxItemName));
				stbHtmlForOrderItems.AppendLine(string.Format("<td colspan='4'>({0})</td>", yeOrder.ShippingMethod));
				stbHtmlForOrderItems.AppendLine(string.Format("<td align='right'>{0:#,##0.00}</td>", yeOrder.OrderShippingInclTax));
				stbHtmlForOrderItems.AppendLine("</tr>");
				computedOrderTotal += yeOrder.OrderShippingInclTax;
				productsIndex++;
			}
			if (yeOrder.OrderDiscount != 0M)
			{
				stbHtmlForOrderItems.AppendLine("<tr>");
				stbHtmlForOrderItems.AppendLine(string.Format("<td align='right'>{0}.</td>", productsIndex));
				stbHtmlForOrderItems.AppendLine(string.Format("<td colspan='5'>{0}</td>", OrderDiscountItemName));
				stbHtmlForOrderItems.AppendLine(string.Format("<td align='right'>{0:#,##0.00}</td>", -yeOrder.OrderDiscount));
				stbHtmlForOrderItems.AppendLine("</tr>");
				computedOrderTotal -= yeOrder.OrderDiscount;
				productsIndex++;
			}
			if (yeOrder.OrderSubTotalDiscountInclTax != 0M)
			{
				stbHtmlForOrderItems.AppendLine("<tr>");
				stbHtmlForOrderItems.AppendLine(string.Format("<td align='right'>{0}.</td>", productsIndex));
				stbHtmlForOrderItems.AppendLine(string.Format("<td colspan='5'>{0}</td>", OrderDiscountItemName));
				stbHtmlForOrderItems.AppendLine(string.Format("<td align='right'>{0:#,##0.00}</td>", -yeOrder.OrderSubTotalDiscountInclTax));
				stbHtmlForOrderItems.AppendLine("</tr>");
				computedOrderTotal -= yeOrder.OrderSubTotalDiscountInclTax;
				productsIndex++;
			}
			stbHtmlForOrderItems.AppendLine("<tr>");
			stbHtmlForOrderItems.AppendLine(string.Format("<td align='right' colspan='6'>{0}</td>", this._localizationService.GetResource("Plugins.Payments.LibraPay.Shopper.OrderTotal")));
			stbHtmlForOrderItems.AppendLine(string.Format("<td align='right'>{0:#,##0.00}</td>", computedOrderTotal));
			stbHtmlForOrderItems.AppendLine("</tr>");
			stbHtmlForOrderItems.AppendLine("</table>");
			preAuthFields.OrderItems = stbHtmlForOrderItems.ToString();
			#endregion
			preAuthFields.PaymentGatewayURL = _LibraPayPaymentSettings.UseSandbox ? LibraPayPaymentSettings.PaymentGatewayURL_Test : LibraPayPaymentSettings.PaymentGatewayURL_Live;
			preAuthFields.UseSandbox = _LibraPayPaymentSettings.UseSandbox;

			return View("~/Plugins/Payments.LibraPay/Views/PaymentLibraPay/AuthorizeRequest.cshtml", preAuthFields);
		}

		/// <summary>
		///		<para>This method is called by the LibraPay payment gateway API after processing the payment authorization. The method marks the order as being authorized by customer for payment.</para>
		///		<para>When the payment is authorized, it means money are blocked on the credit card for the order, waiting to be fetched by the merchant through "capture" after the order is delivered.</para>
		/// </summary>
		/// <returns></returns>
		public ActionResult Authorize()
		{
			StringBuilder stb = new StringBuilder();
			AuthorizeModel preAuthFields = new AuthorizeModel();
			int SalesOrderIdFromPreAuthResponse;
			Order yeOrder = null;
			OrderNote orderNote = new OrderNote();
			orderNote.DisplayToCustomer = false;
			orderNote.CreatedOnUtc = DateTime.Now.ToUniversalTime();
			#region attempt to identify an actual existing order from the response
			if (string.IsNullOrEmpty(Request.QueryString["ORDER"]))
			{
				preAuthFields.ORDER = Request.Form["ORDER"];
			}
			else preAuthFields.ORDER = Request.QueryString["ORDER"];
			if (!string.IsNullOrEmpty(preAuthFields.ORDER))
			{
				if (int.TryParse(preAuthFields.ORDER, out SalesOrderIdFromPreAuthResponse))
				{
					// Remember that we added 1.000.000.000 to the Order ID when we requested payment authorization!
					// That was done due to minimum Order ID length requirement (and no leading 0s were allowed)
					SalesOrderIdFromPreAuthResponse = SalesOrderIdFromPreAuthResponse - 1000000000;
					yeOrder = this._orderService.GetOrderById(SalesOrderIdFromPreAuthResponse);
				}
			}
			if (yeOrder == null || yeOrder.Deleted)
			{
				stb.Append("Plugin.Payments.LibraPay: error occured while processing payment gateway PreAuth response for order identifier: ");
				stb.Append(string.IsNullOrEmpty(preAuthFields.ORDER) ? "[not present in response]" : preAuthFields.ORDER);
				stb.AppendLine(". ");
				stb.AppendLine("The payment gateway has returned a Pre-Auth response referring to an order that does not exist. ");
				stb.AppendLine("ORDER = '" + preAuthFields.ORDER + "'. ");
				_logger.Error(stb.ToString());
				ViewBag.ErrorTitle = this._localizationService.GetResource("Plugins.Payments.LibraPay.Error.PaymentFailure");
				ViewBag.ErrorMessage = string.Format(this._localizationService.GetResource("Plugins.Payments.LibraPay.Error.OrderMissing"), preAuthFields.ORDER);
				return View("~/Plugins/Payments.LibraPay/Views/PaymentLibraPay/Authorize.cshtml");
			}
			#endregion
			#region validate if all required fields exist
			List<string> msgMissingFields = new List<string>();
			if (string.IsNullOrEmpty(Request.QueryString["TERMINAL"]))
			{
				if (string.IsNullOrEmpty(Request.Form["TERMINAL"])) msgMissingFields.Add("TERMINAL");
				else preAuthFields.TERMINAL = Request.Form["TERMINAL"];
			}
			else preAuthFields.TERMINAL = Request.QueryString["TERMINAL"];
			if (string.IsNullOrEmpty(Request.QueryString["TRTYPE"]))
			{
				if (string.IsNullOrEmpty(Request.Form["TRTYPE"])) msgMissingFields.Add("TRTYPE");
				else preAuthFields.TRTYPE = Request.Form["TRTYPE"];
			}
			else preAuthFields.TRTYPE = Request.QueryString["TRTYPE"];
			if (string.IsNullOrEmpty(Request.QueryString["ORDER"]))
			{
				if (string.IsNullOrEmpty(Request.Form["ORDER"])) msgMissingFields.Add("ORDER");
				else preAuthFields.ORDER = Request.Form["ORDER"];
			}
			else preAuthFields.ORDER = Request.QueryString["ORDER"];
			if (string.IsNullOrEmpty(Request.QueryString["AMOUNT"]))
			{
				if (string.IsNullOrEmpty(Request.Form["AMOUNT"])) msgMissingFields.Add("AMOUNT");
				else preAuthFields.AMOUNT = Request.Form["AMOUNT"];
			}
			else preAuthFields.AMOUNT = Request.QueryString["AMOUNT"];
			if (string.IsNullOrEmpty(Request.QueryString["CURRENCY"]))
			{
				if (string.IsNullOrEmpty(Request.Form["CURRENCY"])) msgMissingFields.Add("CURRENCY");
				else preAuthFields.CURRENCY = Request.Form["CURRENCY"];
			}
			else preAuthFields.CURRENCY = Request.QueryString["CURRENCY"];
			if (string.IsNullOrEmpty(Request.QueryString["DESC"]))
			{
				if (string.IsNullOrEmpty(Request.Form["DESC"])) msgMissingFields.Add("DESC");
				else preAuthFields.DESC = Request.Form["DESC"];
			}
			else preAuthFields.DESC = Request.QueryString["DESC"];
			if (string.IsNullOrEmpty(Request.QueryString["ACTION"]))
			{
				if (string.IsNullOrEmpty(Request.Form["ACTION"])) msgMissingFields.Add("ACTION parameter was not.");
				else preAuthFields.ACTION = Request.Form["ACTION"];
			}
			else preAuthFields.ACTION = Request.QueryString["ACTION"];
			if (string.IsNullOrEmpty(Request.QueryString["RC"]))
			{
				if (string.IsNullOrEmpty(Request.Form["RC"])) msgMissingFields.Add("RC");
				else preAuthFields.RC = Request.Form["RC"];
			}
			else preAuthFields.RC = Request.QueryString["RC"];
			if (string.IsNullOrEmpty(Request.QueryString["MESSAGE"]))
			{
				if (string.IsNullOrEmpty(Request.Form["MESSAGE"])) msgMissingFields.Add("MESSAGE");
				else preAuthFields.MESSAGE = Request.Form["MESSAGE"];
			}
			else preAuthFields.MESSAGE = Request.QueryString["MESSAGE"];
			if (string.IsNullOrEmpty(Request.QueryString["RRN"]))
			{
				if (string.IsNullOrEmpty(Request.Form["RRN"])) msgMissingFields.Add("RRN");
				else preAuthFields.RRN = Request.Form["RRN"];
			}
			else preAuthFields.RRN = Request.QueryString["RRN"];
			if (string.IsNullOrEmpty(Request.QueryString["INT_REF"]))
			{
				if (string.IsNullOrEmpty(Request.Form["INT_REF"])) msgMissingFields.Add("INT_REF");
				else preAuthFields.INT_REF = Request.Form["INT_REF"];
			}
			else preAuthFields.INT_REF = Request.QueryString["INT_REF"];
			if (string.IsNullOrEmpty(Request.QueryString["APPROVAL"]))
			{
				if (string.IsNullOrEmpty(Request.Form["APPROVAL"])) msgMissingFields.Add("APPROVAL");
				else preAuthFields.APPROVAL = Request.Form["APPROVAL"];
			}
			else preAuthFields.APPROVAL = Request.QueryString["APPROVAL"];
			if (string.IsNullOrEmpty(Request.QueryString["TIMESTAMP"]))
			{
				if (string.IsNullOrEmpty(Request.Form["TIMESTAMP"])) msgMissingFields.Add("TIMESTAMP");
				else preAuthFields.TIMESTAMP = Request.Form["TIMESTAMP"];
			}
			else preAuthFields.TIMESTAMP = Request.QueryString["TIMESTAMP"];
			if (string.IsNullOrEmpty(Request.QueryString["NONCE"]))
			{
				if (string.IsNullOrEmpty(Request.Form["NONCE"])) msgMissingFields.Add("NONCE");
				else preAuthFields.NONCE = Request.Form["NONCE"];
			}
			else preAuthFields.NONCE = Request.QueryString["NONCE"];
			if (string.IsNullOrEmpty(Request.QueryString["P_SIGN"]))
			{
				if (string.IsNullOrEmpty(Request.Form["P_SIGN"])) msgMissingFields.Add("P_SIGN");
				else preAuthFields.P_SIGN = Request.Form["P_SIGN"];
			}
			else preAuthFields.P_SIGN = Request.QueryString["P_SIGN"];
			if (msgMissingFields.Count > 0)
			{
				stb.Append("Plugin.Payments.LibraPay: error occured while processing payment gateway PreAuth response for order identifier: ");
				stb.Append(string.IsNullOrEmpty(preAuthFields.ORDER) ? "[not present in response]" : preAuthFields.ORDER);
				stb.AppendLine(". ");
				stb.AppendLine("The payment gateway has returned an invalid PreAuth response. The following parameter(s) could not be found in the message from LibraPay: ");
				foreach (string prm in msgMissingFields) stb.AppendLine(string.Format("{0} parameter is missing. ", prm));
				_logger.Error(stb.ToString());
				orderNote.Note = stb.ToString();
				yeOrder.OrderNotes.Add(orderNote);
				_orderService.UpdateOrder(yeOrder);
				ViewBag.ErrorTitle = this._localizationService.GetResource("Plugins.Payments.LibraPay.Error.PaymentFailure");
				ViewBag.ErrorMessage = string.Format(this._localizationService.GetResource("Plugins.Payments.LibraPay.Error.PreAuthFields"), yeOrder.Id);
				return View("~/Plugins/Payments.LibraPay/Views/PaymentLibraPay/Authorize.cshtml");
			}
			#endregion
			#region check the P_SIGN transaction signature
			string computedPSign = preAuthFields.ComputePSign_AuthorizeResponse(_LibraPayPaymentSettings.EncryptionKey);
			if (preAuthFields.P_SIGN != computedPSign)
			{
				stb.AppendLine(string.Format("Plugin.Payments.LibraPay: error occured while processing payment gateway PreAuth response for order number: {0}. ", yeOrder.Id));
				stb.AppendLine("The payment gateway has returned an invalid payment Pre-Auth response. P_SIGN security field did not match; looks like a forgery. ");
				stb.AppendLine("TERMINAL = " + preAuthFields.TERMINAL + "; ");
				stb.AppendLine("TRTYPE = " + preAuthFields.TRTYPE + "; ");
				stb.AppendLine("ORDER = " + preAuthFields.ORDER + "; ");
				stb.AppendLine("AMOUNT = " + preAuthFields.AMOUNT + "; ");
				stb.AppendLine("CURRENCY = " + preAuthFields.CURRENCY + "; ");
				stb.AppendLine("DESC = " + preAuthFields.DESC + "; ");
				stb.AppendLine("ACTION = " + preAuthFields.ACTION + "; ");
				stb.AppendLine("RC = " + preAuthFields.RC + "; ");
				stb.AppendLine("MESSAGE = " + preAuthFields.MESSAGE + "; ");
				stb.AppendLine("RRN = " + preAuthFields.RRN + "; ");
				stb.AppendLine("INT_REF = " + preAuthFields.INT_REF + "; ");
				stb.AppendLine("APPROVAL = " + preAuthFields.APPROVAL + "; ");
				stb.AppendLine("TIMESTAMP = " + preAuthFields.TIMESTAMP + "; ");
				stb.AppendLine("NONCE = " + preAuthFields.NONCE + "; ");
				stb.AppendLine("P_SIGN = " + preAuthFields.P_SIGN + "; ");
				stb.AppendLine("Computed P_SIGN = " + computedPSign + ". ");
				_logger.Error(stb.ToString());
				orderNote.Note = stb.ToString();
				yeOrder.OrderNotes.Add(orderNote);
				_orderService.UpdateOrder(yeOrder);
				ViewBag.ErrorTitle = this._localizationService.GetResource("Plugins.Payments.LibraPay.Error.PaymentFailure");
				ViewBag.ErrorMessage = string.Format(this._localizationService.GetResource("Plugins.Payments.LibraPay.Error.PreAuthSignature"), yeOrder.Id);
				return View("~/Plugins/Payments.LibraPay/Views/PaymentLibraPay/Authorize.cshtml");
			}
			#endregion
			#region check if the payment authorization has been approved
			if (preAuthFields.ACTION != "0" || string.IsNullOrEmpty(preAuthFields.APPROVAL))
			{
				stb.AppendLine(string.Format("Plugin.Payments.LibraPay: error occured while processing payment gateway PreAuth response for order number: {0}. ", yeOrder.Id));
				stb.AppendLine("The payment gateway notified there was a problem with a payment transaction. Pre-Auth response from LibraPay is: ");
				stb.AppendLine("ACTION = " + preAuthFields.ACTION + "; ");
				stb.AppendLine("RC = " + preAuthFields.RC + "; ");
				stb.AppendLine("MESSAGE = " + preAuthFields.MESSAGE + "; ");
				stb.AppendLine("RRN = " + preAuthFields.RRN + "; ");
				stb.AppendLine("INT_REF = " + preAuthFields.INT_REF + "; ");
				stb.AppendLine("APPROVAL = " + preAuthFields.APPROVAL + ". ");
				string actionStatus;
				switch (preAuthFields.ACTION)
				{
					case "0": actionStatus = "Transaction is approved"; break;
					case "1": actionStatus = "Duplicate transaction"; break;
					case "2": actionStatus = "Transaction is rejected"; break;
					case "3": actionStatus = "Transaction processing error"; break;
					default: actionStatus = ""; break;
				}
				stb.AppendLine("ACTION parameter says: " + actionStatus + ". ");
				stb.AppendLine("RC parameter says: " + preAuthFields.MESSAGE + ". ");
				_logger.Warning(stb.ToString());
				orderNote.Note = stb.ToString();
				yeOrder.OrderNotes.Add(orderNote);
				_orderService.UpdateOrder(yeOrder);
				ViewBag.ErrorTitle = this._localizationService.GetResource("Plugins.Payments.LibraPay.Error.PaymentFailure");
				ViewBag.ErrorMessage = string.Format(this._localizationService.GetResource("Plugins.Payments.LibraPay.Error.PreAuthApproval"), actionStatus, preAuthFields.MESSAGE, yeOrder.Id);
				return View("~/Plugins/Payments.LibraPay/Views/PaymentLibraPay/Authorize.cshtml");
			}
			#endregion
			#region validate order info, make sure the order has been fully payed, in the order currency
			if (yeOrder.OrderStatus != OrderStatus.Pending)
			{
				stb.AppendLine(string.Format("Plugin.Payments.LibraPay: error occured while processing payment gateway PreAuth response for order number: {0}. ", yeOrder.Id));
				stb.AppendLine(string.Format("The payment gateway has returned a Pre-Auth notification referring to an order that is not pending payment status. Customer username {0}. ", yeOrder.Customer.Username));
				stb.AppendLine(string.Format("Current order status = {0}. ", yeOrder.OrderStatus));
				_logger.Error(stb.ToString());
				orderNote.Note = stb.ToString();
				yeOrder.OrderNotes.Add(orderNote);
				_orderService.UpdateOrder(yeOrder);
				ViewBag.ErrorTitle = this._localizationService.GetResource("Plugins.Payments.LibraPay.Error.PaymentFailure");
				ViewBag.ErrorMessage = string.Format(this._localizationService.GetResource("Plugins.Payments.LibraPay.Error.PreAuthOrderStatus"), yeOrder.Id, yeOrder.Customer.Username);
				return View("~/Plugins/Payments.LibraPay/Views/PaymentLibraPay/Authorize.cshtml");
			}
			decimal PayedAmount = decimal.Parse(preAuthFields.AMOUNT, NumberStyles.AllowDecimalPoint, CultureInfo.GetCultureInfo("en-us"));
			if (Math.Abs(yeOrder.OrderTotal - PayedAmount) > _LibraPayPaymentSettings.AdditionalFee + 1)
			{
				stb.Append(string.Format("Plugin.Payments.LibraPay: error occured while processing payment gateway PreAuth response for order number: {0}. ", yeOrder.Id));
				stb.AppendLine(string.Format("The payment gateway has returned a Pre-Auth notification, but the payment amount does not match the order value. Customer username {0}. ", yeOrder.Customer.Username));
				stb.AppendLine(string.Format("AMOUNT = {0}. ", preAuthFields.AMOUNT));
				stb.AppendLine(string.Format("Order.OrderTotal = {0}; PaymentMethodAdditionalFee = {1}. ", yeOrder.OrderTotal, _LibraPayPaymentSettings.AdditionalFee));
				_logger.Error(stb.ToString());
				orderNote.Note = stb.ToString();
				yeOrder.OrderNotes.Add(orderNote);
				_orderService.UpdateOrder(yeOrder);
				ViewBag.ErrorTitle = this._localizationService.GetResource("Plugins.Payments.LibraPay.Error.PaymentFailure");
				ViewBag.ErrorMessage = string.Format(this._localizationService.GetResource("Plugins.Payments.LibraPay.Error.PreAuthAmount"), yeOrder.Id, yeOrder.Customer.Username);
				return View("~/Plugins/Payments.LibraPay/Views/PaymentLibraPay/Authorize.cshtml");
			}
			if (yeOrder.CustomerCurrencyCode.ToUpper() != preAuthFields.CURRENCY.ToUpper())
			{
				stb.Append(string.Format("Plugin.Payments.LibraPay: error occured while processing payment gateway PreAuth response for order number: {0}. ", yeOrder.Id));
				stb.AppendLine(string.Format("The payment gateway has returned a Pre-Auth notification, but the payment currency is wrong. Customer username {0}. ", yeOrder.Customer.Username));
				stb.AppendLine(string.Format("CURRENCY = {0}. ", preAuthFields.CURRENCY.ToUpper()));
				stb.AppendLine(string.Format("Order.CustomerCurrencyCode = {0}. ", yeOrder.CustomerCurrencyCode));
				_logger.Error(stb.ToString());
				orderNote.Note = stb.ToString();
				yeOrder.OrderNotes.Add(orderNote);
				_orderService.UpdateOrder(yeOrder);
				ViewBag.ErrorTitle = this._localizationService.GetResource("Plugins.Payments.LibraPay.Error.PaymentFailure");
				ViewBag.ErrorMessage = string.Format(this._localizationService.GetResource("Plugins.Payments.LibraPay.Error.PreAuthCurrency"), yeOrder.Id, yeOrder.Customer.Username);
				return View("~/Plugins/Payments.LibraPay/Views/PaymentLibraPay/Authorize.cshtml");
			}
			#endregion
			yeOrder.AuthorizationTransactionId = "LibraPay Pre-Auth RRN: " + preAuthFields.RRN;
			yeOrder.AuthorizationTransactionCode = "LibraPay Pre-Auth INT_REF: " + preAuthFields.INT_REF;
			yeOrder.AuthorizationTransactionResult = "LibraPay Pre-Auth APPROVAL: " + preAuthFields.APPROVAL;
			yeOrder.PaymentStatus = PaymentStatus.Authorized;
			yeOrder.OrderStatus = OrderStatus.Processing;
			yeOrder.PaidDateUtc = DateTime.Now.ToUniversalTime();
			yeOrder.PaymentMethodSystemName = "Payments.LibraPay";
			orderNote.Note = this._localizationService.GetResource("Plugins.Payments.LibraPay.Note.PaymentSuccessfullyAuthorized");
			yeOrder.OrderNotes.Add(orderNote);
			_orderService.UpdateOrder(yeOrder);
			return RedirectToAction("Authorized", new { OrderID = yeOrder.Id });
		}

		/// <summary>
		///		<para>This method is called by the LibraPay payment gateway API asyncronously. The method marks the order as being authorized by customer for payment, then returns "1".</para>
		///		<para>The call is done after processing of the payment authorization request, when the connection with shopper browser accidentally breaks (thus making the syncronous call impossible).</para>
		///		<para>When the payment is authorized, it means money are blocked on the credit card for the order, waiting to be fetched by the merchant through "capture" after the order is delivered.</para>
		/// </summary>
		/// <returns></returns>
		public byte Authorize_IPN()
		{
			StringBuilder stb = new StringBuilder();
			AuthorizeModel preAuthFields = new AuthorizeModel();
			int SalesOrderIdFromPreAuthResponse;
			Order yeOrder = null;
			OrderNote orderNote = new OrderNote();
			orderNote.DisplayToCustomer = false;
			orderNote.CreatedOnUtc = DateTime.Now.ToUniversalTime();
			#region attempt to identify an actual existing order from the response
			if (string.IsNullOrEmpty(Request.QueryString["ORDER"]))
			{
				preAuthFields.ORDER = Request.Form["ORDER"];
			}
			else preAuthFields.ORDER = Request.QueryString["ORDER"];
			if (!string.IsNullOrEmpty(preAuthFields.ORDER))
			{
				if (int.TryParse(preAuthFields.ORDER, out SalesOrderIdFromPreAuthResponse))
				{
					// Remember that we added 1.000.000.000 to the Order ID when we requested payment authorization!
					// That was done due to minimum Order ID length requirement (and no leading 0s were allowed)
					SalesOrderIdFromPreAuthResponse = SalesOrderIdFromPreAuthResponse - 1000000000;
					yeOrder = this._orderService.GetOrderById(SalesOrderIdFromPreAuthResponse);
				}
			}
			if (yeOrder == null || yeOrder.Deleted)
			{
				stb.Append("Plugin.Payments.LibraPay: error occured while processing payment gateway PreAuth response for order identifier: ");
				stb.Append(string.IsNullOrEmpty(preAuthFields.ORDER) ? "[not present in response]" : preAuthFields.ORDER);
				stb.AppendLine(". ");
				stb.AppendLine("The payment gateway has returned a Pre-Auth response referring to an order that does not exist. ");
				stb.AppendLine("ORDER = '" + preAuthFields.ORDER + "'.");
				_logger.Error(stb.ToString());
				return 1;
			}
			#endregion
			#region validate if all required fields exist
			List<string> msgMissingFields = new List<string>();
			if (string.IsNullOrEmpty(Request.QueryString["TERMINAL"]))
			{
				if (string.IsNullOrEmpty(Request.Form["TERMINAL"])) msgMissingFields.Add("TERMINAL");
				else preAuthFields.TERMINAL = Request.Form["TERMINAL"];
			}
			else preAuthFields.TERMINAL = Request.QueryString["TERMINAL"];
			if (string.IsNullOrEmpty(Request.QueryString["TRTYPE"]))
			{
				if (string.IsNullOrEmpty(Request.Form["TRTYPE"])) msgMissingFields.Add("TRTYPE");
				else preAuthFields.TRTYPE = Request.Form["TRTYPE"];
			}
			else preAuthFields.TRTYPE = Request.QueryString["TRTYPE"];
			if (string.IsNullOrEmpty(Request.QueryString["ORDER"]))
			{
				if (string.IsNullOrEmpty(Request.Form["ORDER"])) msgMissingFields.Add("ORDER");
				else preAuthFields.ORDER = Request.Form["ORDER"];
			}
			else preAuthFields.ORDER = Request.QueryString["ORDER"];
			if (string.IsNullOrEmpty(Request.QueryString["AMOUNT"]))
			{
				if (string.IsNullOrEmpty(Request.Form["AMOUNT"])) msgMissingFields.Add("AMOUNT");
				else preAuthFields.AMOUNT = Request.Form["AMOUNT"];
			}
			else preAuthFields.AMOUNT = Request.QueryString["AMOUNT"];
			if (string.IsNullOrEmpty(Request.QueryString["CURRENCY"]))
			{
				if (string.IsNullOrEmpty(Request.Form["CURRENCY"])) msgMissingFields.Add("CURRENCY");
				else preAuthFields.CURRENCY = Request.Form["CURRENCY"];
			}
			else preAuthFields.CURRENCY = Request.QueryString["CURRENCY"];
			if (string.IsNullOrEmpty(Request.QueryString["DESC"]))
			{
				if (string.IsNullOrEmpty(Request.Form["DESC"])) msgMissingFields.Add("DESC");
				else preAuthFields.DESC = Request.Form["DESC"];
			}
			else preAuthFields.DESC = Request.QueryString["DESC"];
			if (string.IsNullOrEmpty(Request.QueryString["ACTION"]))
			{
				if (string.IsNullOrEmpty(Request.Form["ACTION"])) msgMissingFields.Add("ACTION parameter was not.");
				else preAuthFields.ACTION = Request.Form["ACTION"];
			}
			else preAuthFields.ACTION = Request.QueryString["ACTION"];
			if (string.IsNullOrEmpty(Request.QueryString["RC"]))
			{
				if (string.IsNullOrEmpty(Request.Form["RC"])) msgMissingFields.Add("RC");
				else preAuthFields.RC = Request.Form["RC"];
			}
			else preAuthFields.RC = Request.QueryString["RC"];
			if (string.IsNullOrEmpty(Request.QueryString["MESSAGE"]))
			{
				if (string.IsNullOrEmpty(Request.Form["MESSAGE"])) msgMissingFields.Add("MESSAGE");
				else preAuthFields.MESSAGE = Request.Form["MESSAGE"];
			}
			else preAuthFields.MESSAGE = Request.QueryString["MESSAGE"];
			if (string.IsNullOrEmpty(Request.QueryString["RRN"]))
			{
				if (string.IsNullOrEmpty(Request.Form["RRN"])) msgMissingFields.Add("RRN");
				else preAuthFields.RRN = Request.Form["RRN"];
			}
			else preAuthFields.RRN = Request.QueryString["RRN"];
			if (string.IsNullOrEmpty(Request.QueryString["INT_REF"]))
			{
				if (string.IsNullOrEmpty(Request.Form["INT_REF"])) msgMissingFields.Add("INT_REF");
				else preAuthFields.INT_REF = Request.Form["INT_REF"];
			}
			else preAuthFields.INT_REF = Request.QueryString["INT_REF"];
			if (string.IsNullOrEmpty(Request.QueryString["APPROVAL"]))
			{
				if (string.IsNullOrEmpty(Request.Form["APPROVAL"])) msgMissingFields.Add("APPROVAL");
				else preAuthFields.APPROVAL = Request.Form["APPROVAL"];
			}
			else preAuthFields.APPROVAL = Request.QueryString["APPROVAL"];
			if (string.IsNullOrEmpty(Request.QueryString["TIMESTAMP"]))
			{
				if (string.IsNullOrEmpty(Request.Form["TIMESTAMP"])) msgMissingFields.Add("TIMESTAMP");
				else preAuthFields.TIMESTAMP = Request.Form["TIMESTAMP"];
			}
			else preAuthFields.TIMESTAMP = Request.QueryString["TIMESTAMP"];
			if (string.IsNullOrEmpty(Request.QueryString["NONCE"]))
			{
				if (string.IsNullOrEmpty(Request.Form["NONCE"])) msgMissingFields.Add("NONCE");
				else preAuthFields.NONCE = Request.Form["NONCE"];
			}
			else preAuthFields.NONCE = Request.QueryString["NONCE"];
			if (string.IsNullOrEmpty(Request.QueryString["P_SIGN"]))
			{
				if (string.IsNullOrEmpty(Request.Form["P_SIGN"])) msgMissingFields.Add("P_SIGN");
				else preAuthFields.P_SIGN = Request.Form["P_SIGN"];
			}
			else preAuthFields.P_SIGN = Request.QueryString["P_SIGN"];
			if (msgMissingFields.Count > 0)
			{
				stb.Append("Plugin.Payments.LibraPay: error occured while processing payment gateway PreAuth response for order identifier: ");
				stb.Append(string.IsNullOrEmpty(preAuthFields.ORDER) ? "[not present in response]" : preAuthFields.ORDER);
				stb.AppendLine(". ");
				stb.AppendLine("The payment gateway has returned an invalid PreAuth response. The following parameter(s) could not be found in the message from LibraPay: ");
				foreach (string prm in msgMissingFields) stb.AppendLine(string.Format("{0} parameter is missing. ", prm));
				_logger.Error(stb.ToString());
				orderNote.Note = stb.ToString();
				yeOrder.OrderNotes.Add(orderNote);
				_orderService.UpdateOrder(yeOrder);
				return 1;
			}
			#endregion
			#region check the P_SIGN transaction signature
			string computedPSign = preAuthFields.ComputePSign_AuthorizeResponse(_LibraPayPaymentSettings.EncryptionKey);
			if (preAuthFields.P_SIGN != computedPSign)
			{
				stb.AppendLine(string.Format("Plugin.Payments.LibraPay: error occured while processing payment gateway PreAuth response for order number: {0}. ", yeOrder.Id));
				stb.AppendLine("The payment gateway has returned an invalid payment Pre-Auth response. P_SIGN security field did not match; looks like a forgery. ");
				stb.AppendLine("TERMINAL = " + preAuthFields.TERMINAL + "; ");
				stb.AppendLine("TRTYPE = " + preAuthFields.TRTYPE + "; ");
				stb.AppendLine("ORDER = " + preAuthFields.ORDER + "; ");
				stb.AppendLine("AMOUNT = " + preAuthFields.AMOUNT + "; ");
				stb.AppendLine("CURRENCY = " + preAuthFields.CURRENCY + "; ");
				stb.AppendLine("DESC = " + preAuthFields.DESC + "; ");
				stb.AppendLine("ACTION = " + preAuthFields.ACTION + "; ");
				stb.AppendLine("RC = " + preAuthFields.RC + "; ");
				stb.AppendLine("MESSAGE = " + preAuthFields.MESSAGE + "; ");
				stb.AppendLine("RRN = " + preAuthFields.RRN + "; ");
				stb.AppendLine("INT_REF = " + preAuthFields.INT_REF + "; ");
				stb.AppendLine("APPROVAL = " + preAuthFields.APPROVAL + "; ");
				stb.AppendLine("TIMESTAMP = " + preAuthFields.TIMESTAMP + "; ");
				stb.AppendLine("NONCE = " + preAuthFields.NONCE + "; ");
				stb.AppendLine("P_SIGN = " + preAuthFields.P_SIGN + "; ");
				stb.AppendLine("Computed P_SIGN = " + computedPSign + ". ");
				_logger.Error(stb.ToString());
				orderNote.Note = stb.ToString();
				yeOrder.OrderNotes.Add(orderNote);
				_orderService.UpdateOrder(yeOrder);
				return 1;
			}
			#endregion
			#region check if the payment authorization has been approved
			if (preAuthFields.ACTION != "0" || string.IsNullOrEmpty(preAuthFields.APPROVAL))
			{
				stb.AppendLine(string.Format("Plugin.Payments.LibraPay: error occured while processing payment gateway PreAuth response for order number: {0}. ", yeOrder.Id));
				stb.AppendLine("The payment gateway notified there was a problem with a payment transaction. Pre-Auth response from LibraPay is: ");
				stb.AppendLine("ACTION = " + preAuthFields.ACTION + "; ");
				stb.AppendLine("RC = " + preAuthFields.RC + "; ");
				stb.AppendLine("MESSAGE = " + preAuthFields.MESSAGE + "; ");
				stb.AppendLine("RRN = " + preAuthFields.RRN + "; ");
				stb.AppendLine("INT_REF = " + preAuthFields.INT_REF + "; ");
				stb.AppendLine("APPROVAL = " + preAuthFields.APPROVAL + ". ");
				string actionStatus;
				switch (preAuthFields.ACTION)
				{
					case "0": actionStatus = "Transaction is approved"; break;
					case "1": actionStatus = "Duplicate transaction"; break;
					case "2": actionStatus = "Transaction is rejected"; break;
					case "3": actionStatus = "Transaction processing error"; break;
					default: actionStatus = ""; break;
				}
				stb.AppendLine("ACTION parameter says: " + actionStatus + ". ");
				stb.AppendLine("RC parameter says: " + preAuthFields.MESSAGE + ". ");
				_logger.Warning(stb.ToString());
				orderNote.Note = stb.ToString();
				yeOrder.OrderNotes.Add(orderNote);
				_orderService.UpdateOrder(yeOrder);
				return 1;
			}
			#endregion
			#region validate order info, make sure the order has been fully payed, in the order currency
			if (yeOrder.OrderStatus != OrderStatus.Pending)
			{
				stb.AppendLine(string.Format("Plugin.Payments.LibraPay: error occured while processing payment gateway PreAuth response for order number: {0}. ", yeOrder.Id));
				stb.AppendLine(string.Format("The payment gateway has returned a Pre-Auth notification referring to an order that is not pending payment status. Customer username {0}. ", yeOrder.Customer.Username));
				stb.AppendLine(string.Format("Current order status = {0}. ", yeOrder.OrderStatus));
				_logger.Error(stb.ToString());
				orderNote.Note = stb.ToString();
				yeOrder.OrderNotes.Add(orderNote);
				_orderService.UpdateOrder(yeOrder);
				return 1;
			}
			decimal PayedAmount = decimal.Parse(preAuthFields.AMOUNT, NumberStyles.AllowDecimalPoint, CultureInfo.GetCultureInfo("en-us"));
			if (Math.Abs(yeOrder.OrderTotal - PayedAmount) > _LibraPayPaymentSettings.AdditionalFee + 1)
			{
				stb.Append(string.Format("Plugin.Payments.LibraPay: error occured while processing payment gateway PreAuth response for order number: {0}. ", yeOrder.Id));
				stb.AppendLine(string.Format("The payment gateway has returned a Pre-Auth notification, but the payment amount does not match the order value. Customer username {0}. ", yeOrder.Customer.Username));
				stb.AppendLine(string.Format("AMOUNT = {0}. ", preAuthFields.AMOUNT));
				stb.AppendLine(string.Format("Order.OrderTotal = {0}; PaymentMethodAdditionalFee = {1}. ", yeOrder.OrderTotal, _LibraPayPaymentSettings.AdditionalFee));
				_logger.Error(stb.ToString());
				orderNote.Note = stb.ToString();
				yeOrder.OrderNotes.Add(orderNote);
				_orderService.UpdateOrder(yeOrder);
				return 1;
			}
			if (yeOrder.CustomerCurrencyCode.ToUpper() != preAuthFields.CURRENCY.ToUpper())
			{
				stb.Append(string.Format("Plugin.Payments.LibraPay: error occured while processing payment gateway PreAuth response for order number: {0}. ", yeOrder.Id));
				stb.AppendLine(string.Format("The payment gateway has returned a Pre-Auth notification, but the payment currency is wrong. Customer username {0}. ", yeOrder.Customer.Username));
				stb.AppendLine(string.Format("CURRENCY = {0}. ", preAuthFields.CURRENCY.ToUpper()));
				stb.AppendLine(string.Format("Order.CustomerCurrencyCode = {0}. ", yeOrder.CustomerCurrencyCode));
				_logger.Error(stb.ToString());
				orderNote.Note = stb.ToString();
				yeOrder.OrderNotes.Add(orderNote);
				_orderService.UpdateOrder(yeOrder);
				return 1;
			}
			#endregion
			yeOrder.AuthorizationTransactionId = "LibraPay Pre-Auth RRN: " + preAuthFields.RRN;
			yeOrder.AuthorizationTransactionCode = "LibraPay Pre-Auth INT_REF: " + preAuthFields.INT_REF;
			yeOrder.AuthorizationTransactionResult = "LibraPay Pre-Auth APPROVAL: " + preAuthFields.APPROVAL;
			yeOrder.PaymentStatus = PaymentStatus.Authorized;
			yeOrder.OrderStatus = OrderStatus.Processing;
			yeOrder.PaidDateUtc = DateTime.Now.ToUniversalTime();
			yeOrder.PaymentMethodSystemName = "Payments.LibraPay";
			orderNote.Note = this._localizationService.GetResource("Plugins.Payments.LibraPay.Note.PaymentSuccessfullyAuthorized");
			yeOrder.OrderNotes.Add(orderNote);
			_orderService.UpdateOrder(yeOrder);
			return 1;
		}

		/// <summary>
		///		<para>Shows the customer a notification on how the payment authorization process went.</para>
		///		<para>This is the final step in Authorize process.</para>
		/// </summary>
		/// <param name="OrderID"></param>
		/// <returns></returns>
		public ViewResult Authorized(int OrderID)
		{
			ViewBag.OrderID = OrderID;
			return View("~/Plugins/Payments.LibraPay/Views/PaymentLibraPay/Authorize.cshtml");
		}

		/// <summary>
		///		<para>No validation: no customer data is collected by the plugin, so no validation actually takes place.</para>
		///		<para>The plugin only does redirects to LibraPay payment gateway API: the customer data is collected and processed there.</para>
		/// </summary>
		/// <param name="form"></param>
		/// <returns>An empty list of warnings</returns>
		[NonAction]
		public override IList<string> ValidatePaymentForm(FormCollection form)
		{
			List<string> warnings = new List<string>();
			return warnings;
		}

		[NonAction]
		public override ProcessPaymentRequest GetPaymentInfo(FormCollection form)
		{
			ProcessPaymentRequest paymentInfo = new ProcessPaymentRequest();
			return paymentInfo;
		}

		[AdminAuthorize]
		[ChildActionOnly]
		public ActionResult CancelOrder(FormCollection form)
		{
			// If the order is in Pending state, we should un-block money on customer credit card account.
			// TO DO: redirect the merchant through the Refund guide for the selected order.
			return RedirectToAction("Index", "Home", new { area = "" });
		}
	}
}